classdef DBwrapper < handle
  % Wraps a Matlab database object w/ frequently-used data and methods
  % Derived from handle
  % Constructor signature: DB = DBwrapper(varargin), 
  %     varargin consisting of one to three arguments: 
  %         the database name (req.), username (opt.), and password (opt.)
  %
  % Author: David Goldsmith, Wash. State Dept. of Ecology, dgol461@ecy.wa.gov
  % Release date: N/A

    properties
        DB;
        err={};
        recordsInProcess = struct('col', {}, 'val', {});
    end
    
    properties (Dependent=true)
        name;
        isopen;
    end
    
    methods
        function DB = DBwrapper(varargin)
            switch nargin
                case 1
                    DB.DB = database(varargin{1}, '', '');
                case 2
                    DB.DB = database(varargin{1}, varargin{2}, '');
                case 3
                    DB.DB = database(varargin{1}, varargin{2}, varargin{3});
            end
            if ~isempty(DB.DB.Message)
                DB.appendErr(DB.DB.Message)
            end
        end
        
        function name = get.name(obj)
            name = obj.DB.Instance;
        end
        
        function isopen = get.isopen(obj)
            isopen = isconnection(obj.DB);
        end
        
        function set.recordsInProcess(obj, recs)
          % recordsInProcess is a two-field struct:
          %   col, a cellstr array, containing the name(s) of the column(s) 
          %                         providing the UIDs for each record
          %   val, a cell array, containing the UID values themselves
          %
          % recs, this setter's input, can contain either:
          %   such a struct (in which case, it is simply assigned to the property
          %     or
          %   a fully-realized query or injoinQuery object to retreive the desired values 

            global lfcr
            
            switch 1
                case isa(recs, 'query') && iscellstr(recs.cols)
                    recs.submitStatement;
                    tmp = recs.structFromResult;
                    obj.recordsInProcess.col = recs.cols;
                    for col=recs.cols
                        obj.recordsInProcess.val{end+1} = tmp.result.(col);
                    end
                case isstruct(recs) && setequal(fieldnames(recs), {'col', 'val'})
                    obj.recordsInProcess = recs;
                otherwise
                    obj.err{end+1} = ['DBwrapper.set.recordsInProcess error: '...
                                      'incorrect input type' lfcr '(view '...
                                      'DBwrapper.set.recordsInProcess help '...
                                      'for accepted input types)'];
            end
        end
        
        function where = allRecInProc(obj)
            n = numel(obj.recordsInProcess.val);
            where = cell(n,1);
            for i=1:n
                where{i} = [obj.recordsInProcess.col{:} '=''' obj.recordsInProcess.val{i} ''''];
            end
        end
        
        function appendErr(obj, msg)
            if ~isempty(msg)
                if isempty(obj.err)
                    obj.err{1} = msg;
                elseif ~strcmp(msg, obj.err{end})
                    obj.err{end+1} = msg;
                end
            end
        end
        
        function close(obj)
            if isconnection(obj.DB)
                close(obj.DB);
                if isconnection(obj.DB)
                    obj.appendErr(['ALERT: attempt to close DB ' obj.name ...
                                   ' failed!'])
                else
                    obj.appendErr([obj.name ' closed.  '])
                end
            end
        end
        
    end
    
end